package com.example.fitts_app

import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.fitts_app.databinding.ActivityChartBinding
import com.github.mikephil.charting.charts.ScatterChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.ScatterData
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.ScatterDataSet
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import android.util.Log


class ChartActivity : AppCompatActivity() {

    private lateinit var binding: ActivityChartBinding

    private var currentXType = "ID"  // 当前正在显示的横轴类型

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityChartBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 初始化图表配置，禁用可能导致问题的功能
        binding.chart.apply {
            clear()
            data = null
            setHighlightPerDragEnabled(false)
            setHighlightPerTapEnabled(false)
            invalidate()
        }

        // 检查数据是否存在
        if (FittsDataHolder.records.isEmpty()) {
            binding.chart.setNoDataText("暂无实验数据，请先完成实验后再查看散点图")
            // 这行点击事件在后面已经写过一次了，这里其实可以去掉，避免重复设置同一个按钮的事件
            // binding.btnBack.setOnClickListener { finish() }
            return
        }

        // 默认显示 T–ID 图
        showScatter("ID")

        binding.btnID.setOnClickListener {
            currentXType = "ID"
            showScatter("ID")
        }
        binding.btnD.setOnClickListener {
            currentXType = "D"
            showScatter("D")
        }
        binding.btnW.setOnClickListener {
            currentXType = "W"
            showScatter("W")
        }
        binding.btnExport.setOnClickListener {
            try {
                exportDataToTxt()
                FittsDataHolder.records.clear()
                Toast.makeText(this, "数据已导出并清除", Toast.LENGTH_SHORT).show()
            } catch (e: Exception) {
                Log.e("ChartActivity", "导出失败", e)
                Toast.makeText(this, "导出失败：${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
        binding.btnBack.setOnClickListener { 
            // 返回时重新启动 MainActivity（因为 MainActivity 已被销毁）
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }


    }

    private fun showScatter(xType: String) {
        try {
            // 每次都重新获取最新数据
            val records = FittsDataHolder.records.toList() // 创建副本避免并发修改
            
            if (records.isEmpty()) {
                binding.chart.clear()
                binding.chart.data = null
                binding.chart.setNoDataText("暂无实验数据")
                return
            }

            // 完全重置图表状态
            binding.chart.apply {
                clear()
                data = null
                setNoDataText("")
                // 重置所有可能导致问题的设置
                notifyDataSetChanged()
                invalidate()
            }
            val entries = mutableListOf<Entry>()

            for (record in records) {
                try {
                    val T = record.T
                    val xValue = when (xType) {
                        "ID" -> record.ID
                        "D" -> record.D
                        "W" -> record.W
                        else -> 0f
                    }

                    // ⚠️ 跳过无效或异常数据
                    if (!xValue.isFinite() || !T.isFinite() || xValue <= 0f || T <= 0f) {
                        continue
                    }

                    entries.add(Entry(xValue, T))
                } catch (e: Exception) {
                    Log.e("ChartActivity", "处理记录时出错", e)
                    continue
                }
            }

            // 无有效点时直接返回
            if (entries.isEmpty()) {
                binding.chart.clear()
                binding.chart.data = null
                binding.chart.setNoDataText("暂无有效数据可显示")
                Toast.makeText(this, "暂无有效数据可显示", Toast.LENGTH_SHORT).show()
                return
            }

            // 先设置安全坐标范围，避免 axis 间距为负
            var minX = entries.minOf { it.x }
            var maxX = entries.maxOf { it.x }
            var minY = entries.minOf { it.y }
            var maxY = entries.maxOf { it.y }

            // 确保所有值都是有效的有限数
            if (!minX.isFinite() || !maxX.isFinite() || !minY.isFinite() || !maxY.isFinite() ||
                minX <= 0f || maxX <= 0f || minY <= 0f || maxY <= 0f) {
                Log.e("ChartActivity", "数据包含无效值: minX=$minX, maxX=$maxX, minY=$minY, maxY=$maxY")
                Toast.makeText(this, "数据包含无效值，无法显示图表", Toast.LENGTH_SHORT).show()
                return
            }

            // 处理所有数据点 X 值相同的情况（例如所有 D 值都是 100）
            if (minX >= maxX) {
                val centerX = if (minX == maxX) minX else (minX + maxX) / 2f
                val range = maxOf(centerX * 0.1f, Math.max(centerX, 1f) * 0.05f, 1f) // 至少 5-10% 的范围，或至少 1 个单位
                minX = maxOf(centerX - range, 0.1f) // 确保最小值是正数
                maxX = centerX + range
                Log.d("ChartActivity", "X 值相同或无效，设置范围: $minX 到 $maxX")
            }

            // 处理所有数据点 Y 值相同的情况
            if (minY >= maxY) {
                val centerY = if (minY == maxY) minY else (minY + maxY) / 2f
                val range = maxOf(centerY * 0.1f, Math.max(centerY, 1f) * 0.05f, 1f) // 至少 5-10% 的范围，或至少 1 个单位
                minY = maxOf(centerY - range, 0.1f) // 确保最小值是正数
                maxY = centerY + range
                Log.d("ChartActivity", "Y 值相同或无效，设置范围: $minY 到 $maxY")
            }

            // 确保坐标范围有效且合理
            val xRange = maxX - minX
            val yRange = maxY - minY
            
            if (xRange <= 0f || yRange <= 0f || !minX.isFinite() || !maxX.isFinite() || !minY.isFinite() || !maxY.isFinite()) {
                Log.e("ChartActivity", "坐标范围无效: minX=$minX, maxX=$maxX, minY=$minY, maxY=$maxY")
                Toast.makeText(this, "数据范围异常，无法显示图表", Toast.LENGTH_SHORT).show()
                return
            }

            // 计算安全的内边距（确保不会产生负数）
            val xPadding = maxOf(xRange * 0.1f, 1f) // 至少 10% 的范围或 1 个单位
            val yPadding = maxOf(yRange * 0.1f, 1f)
            
            val finalMinX = maxOf(minX - xPadding, 0f) // 确保最小值不为负
            val finalMaxX = maxX + xPadding
            val finalMinY = maxOf(minY - yPadding, 0f) // 确保最小值不为负
            val finalMaxY = maxY + yPadding

            // 再次验证最终值
            if (finalMinX >= finalMaxX || finalMinY >= finalMaxY || 
                !finalMinX.isFinite() || !finalMaxX.isFinite() || !finalMinY.isFinite() || !finalMaxY.isFinite()) {
                Log.e("ChartActivity", "最终坐标范围无效: minX=$finalMinX, maxX=$finalMaxX, minY=$finalMinY, maxY=$finalMaxY")
                Toast.makeText(this, "数据范围异常，无法显示图表", Toast.LENGTH_SHORT).show()
                return
            }

            // 先配置图表和坐标轴，再设置数据
            binding.chart.apply {
                // 先禁用所有可能导致问题的功能
                setHighlightPerDragEnabled(false)
                setHighlightPerTapEnabled(false)
                
                // 配置坐标轴
                xAxis.apply {
                    axisMinimum = finalMinX
                    axisMaximum = finalMaxX
                    position = XAxis.XAxisPosition.BOTTOM
                    setDrawGridLines(false)
                    setDrawLabels(true)
                }
                
                axisLeft.apply {
                    axisMinimum = finalMinY
                    axisMaximum = finalMaxY
                    setDrawGridLines(false)
                }
                
                axisRight.isEnabled = false
                description.text = "T vs $xType"
                legend.isEnabled = false
                setScaleEnabled(true)
                setPinchZoom(true)
                
                // 现在设置数据
                val dataSet = ScatterDataSet(entries, "T vs $xType").apply {
                    color = Color.BLUE
                    setScatterShape(ScatterChart.ScatterShape.CIRCLE)
                    scatterShapeSize = 10f
                    setDrawValues(false) // 在数据集级别也禁用
                    setDrawIcons(false)
                }
                
                val scatterData = ScatterData(dataSet)
                data = scatterData
                
                // 最后调用 invalidate
                invalidate()
            }
            Log.d("ChartActivity", "绘制 ${entries.size} 个有效散点，X范围: $finalMinX-$finalMaxX, Y范围: $finalMinY-$finalMaxY")
        } catch (e: Exception) {
            Log.e("ChartActivity", "显示散点图时出错", e)
            Toast.makeText(this, "显示图表时出错：${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        binding.chart.clear()
        binding.chart.data = null
    }




    private fun exportDataToTxt() {
        try {
            val records = FittsDataHolder.records

            if (records.isEmpty()) {
                Toast.makeText(this, "暂无可导出的数据", Toast.LENGTH_SHORT).show()
                return
            }

            // 1️⃣ 构建文件内容
            val sb = StringBuilder()
            sb.append("D(pixel)\tW(pixel)\tID(bits)\tMT(ms)\n")
            for (record in records) {
                val D = record.D
                val W = record.W
                val ID = record.ID
                val T = record.T
                sb.append("$D\t$W\t${String.format("%.2f", ID)}\t${String.format("%.2f", T)}\n")
            }

            // 生成文件名和路径
            val now = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()).format(Date())
            val exportDir = File(getExternalFilesDir("exports"), "")
            if (!exportDir.exists()) exportDir.mkdirs()
            val file = File(exportDir, "records_$now.txt")

            // 写入文件
            file.writeText(sb.toString(), Charsets.UTF_8)

            // 提示路径
            Toast.makeText(this, "数据已导出至：\n${file.absolutePath}", Toast.LENGTH_LONG).show()

        } catch (e: Exception) {
            e.printStackTrace()
            Toast.makeText(this, "导出失败：${e.message}", Toast.LENGTH_LONG).show()
        }
    }







}
